#ifndef _VECTOR
#define _VECTOR

#include "base.h"

// TYPEDEFS --------------------------------------------------------------------------
typedef struct
{
  union
  {
    fNumber x, y;
    fNumber v[2]; // [x,y]
  };
} vector2;

typedef struct
{
  union
  {
    fNumber x, y, z;
    fNumber v[3]; // [x,y,z]
  };
} vector3;

typedef struct
{
  union
  {
    fNumber x, y, z, w;
    fNumber v[4]; // [x,y,z,w]
  };
} vector4;

// FUNCTIONS -------------------------------------------------------------------------

/* GENERAL:
   size  -> array size (0,1 for single elements)

   v,a,b -> arbitrary vertices
   k     -> floating point scalar */

// printf() for vector2/3/4
void vector2Printf(vector2* v);
void vector3Printf(vector3* v);
void vector4Printf(vector4* v);

// size: {0,1} -> single element
void vector2Clear(vector2 *v, ui32 size);            // v = [0,0]
void vector3Clear(vector3 *v, ui32 size);            // v = [0,0,0]
void vector4Clear(vector4 *v, ui32 size);            // v = [0,0,0,1]

// v = a
void vector2Copy(vector2 *v, vector2 *a, ui32 size);
void vector3Copy(vector3 *v, vector3 *a, ui32 size);
void vector4Copy(vector4 *v, vector4 *a, ui32 size);

// ----> basic properties ------------------------------------------------------------
// total displacement
fNumber vector2Magnitude(vector2* v);
fNumber vector3Magnitude(vector3* v);
fNumber vector4Magnitude(vector4* v);

// normalization: v -> to range (-)[0,1]
void    vector2Normalize(vector2* v);
void    vector3Normalize(vector3* v);
void    vector4Normalize(vector4* v);							

// inverse: v -> -(v)
void    vector2Inverse  (vector2* v);
void    vector3Inverse  (vector3* v);
void    vector4Inverse  (vector4* v);

// ----> addition --------------------------------------------------------------------
// v = a + b
void vector2Add    (vector2* v, vector2* a, vector2* b);
void vector3Add    (vector3* v, vector3* a, vector3* b);
void vector4Add    (vector4* v, vector4* a, vector4* b);

// v += a
void vector2AddThis(vector2* v, vector2* a);
void vector3AddThis(vector3* v, vector3* a);
void vector4AddThis(vector4* v, vector4* a);

// ----> subtraction -----------------------------------------------------------------
// v = a - b
void vector2Subtract    (vector2* v, vector2* a, vector2* b);
void vector3Subtract    (vector3* v, vector3* a, vector3* b);
void vector4Subtract    (vector4* v, vector4* a, vector4* b);

// v -= a
void vector2SubtractThis(vector2* v, vector2* a);
void vector3SubtractThis(vector3* v, vector3* a);
void vector4SubtractThis(vector4* v, vector4* a);

// ----> scalar multiplication -------------------------------------------------------
// v = a * k
void vector2Multiply    (vector2* v, vector2* a, fNumber k);
void vector3Multiply    (vector3* v, vector3* a, fNumber k);
void vector4Multiply    (vector4* v, vector4* a, fNumber k);

// v *= k
void vector2MultiplyThis(vector2* v, fNumber k);
void vector3MultiplyThis(vector3* v, fNumber k);
void vector4MultiplyThis(vector4* v, fNumber k);

// ----> scalar division -------------------------------------------------------------
// v = a / k
void vector2Divide    (vector2* v, vector2* a, fNumber k);
void vector3Divide    (vector3* v, vector3* a, fNumber k);
void vector4Divide    (vector4* v, vector4* a, fNumber k);

// v /= k
void vector2DivideThis(vector2* v, fNumber k);
void vector3DivideThis(vector3* v, fNumber k);
void vector4DivideThis(vector4* v, fNumber k);

// ----> (in)equality ----------------------------------------------------------------
// a == b
bool vector2Equals(vector2* a, vector2* b);
bool vector3Equals(vector3* a, vector3* b);
bool vector4Equals(vector4* a, vector4* b);

// a != b
bool vector2InEquals(vector2* a, vector2* b);
bool vector3InEquals(vector3* a, vector3* b);
bool vector4InEquals(vector4* a, vector4* b);

// ----> scalar product --------------------------------------------------------------
// scalar product of v, a
fNumber vectorScalarProduct(vector3* v, vector3* a);

// ----> vector product --------------------------------------------------------------
// v = vector product of a,b
void vectorVectorProduct(vector3* v, vector3* a, vector3* b);	

#endif // _VECTOR
